package billing

import (
	"fmt"
	"log"
	"sync"
	"time"
)

// ========================================
// 流量配额拦截器 (Traffic Quota Interceptor)
// 用于控制用户的流量使用，超出配额后拦截请求
// ========================================

// TrafficQuota 流量配额信息
type TrafficQuota struct {
	UserID        string    // 用户ID
	TotalQuota    int64     // 总配额（字节）
	UsedQuota     int64     // 已使用配额（字节）
	ResetTime     time.Time // 配额重置时间
	PaymentType   PaymentType
	PaymentURL    string // 付费URL（收银台或二维码）
	OrderID       string // 订单号
	LastCheckTime time.Time
}

// TrafficQuotaStorage 流量配额存储接口
// 可以实现为内存存储、Redis存储、数据库存储等
type TrafficQuotaStorage interface {
	// GetQuota 获取用户的流量配额
	GetQuota(userID string) (*TrafficQuota, error)

	// UpdateUsage 更新流量使用量
	UpdateUsage(userID string, usedBytes int64) error

	// IsQuotaExceeded 检查是否超出配额
	IsQuotaExceeded(userID string) (bool, *TrafficQuota, error)
}

// InMemoryQuotaStorage 内存存储实现（用于开发/测试）
type InMemoryQuotaStorage struct {
	quotas map[string]*TrafficQuota
	mu     sync.RWMutex
}

// NewInMemoryQuotaStorage 创建内存存储
func NewInMemoryQuotaStorage() *InMemoryQuotaStorage {
	return &InMemoryQuotaStorage{
		quotas: make(map[string]*TrafficQuota),
	}
}

// SetQuota 设置用户配额（仅用于测试/演示）
func (s *InMemoryQuotaStorage) SetQuota(userID string, totalQuota int64, paymentType PaymentType, paymentURL, orderID string) {
	s.mu.Lock()
	defer s.mu.Unlock()

	s.quotas[userID] = &TrafficQuota{
		UserID:        userID,
		TotalQuota:    totalQuota,
		UsedQuota:     0,
		ResetTime:     time.Now().Add(30 * 24 * time.Hour), // 30天后重置
		PaymentType:   paymentType,
		PaymentURL:    paymentURL,
		OrderID:       orderID,
		LastCheckTime: time.Now(),
	}
}

// GetQuota 获取配额
func (s *InMemoryQuotaStorage) GetQuota(userID string) (*TrafficQuota, error) {
	s.mu.RLock()
	defer s.mu.RUnlock()

	quota, exists := s.quotas[userID]
	if !exists {
		// 🚀 默认策略：新用户给予10GB免费流量
		return &TrafficQuota{
			UserID:        userID,
			TotalQuota:    10 * 1024 * 1024 * 1024, // 10GB
			UsedQuota:     0,
			ResetTime:     time.Now().Add(30 * 24 * time.Hour),
			PaymentType:   PaymentTypeCashier,
			PaymentURL:    fmt.Sprintf("https://pay.example.com/checkout?user=%s", userID),
			OrderID:       fmt.Sprintf("ORDER-%s-%d", userID, time.Now().Unix()),
			LastCheckTime: time.Now(),
		}, nil
	}

	return quota, nil
}

// UpdateUsage 更新使用量
func (s *InMemoryQuotaStorage) UpdateUsage(userID string, usedBytes int64) error {
	s.mu.Lock()
	defer s.mu.Unlock()

	quota, exists := s.quotas[userID]
	if !exists {
		// 如果不存在，创建默认配额
		quota = &TrafficQuota{
			UserID:        userID,
			TotalQuota:    10 * 1024 * 1024 * 1024,
			UsedQuota:     0,
			ResetTime:     time.Now().Add(30 * 24 * time.Hour),
			PaymentType:   PaymentTypeCashier,
			PaymentURL:    fmt.Sprintf("https://pay.example.com/checkout?user=%s", userID),
			OrderID:       fmt.Sprintf("ORDER-%s-%d", userID, time.Now().Unix()),
			LastCheckTime: time.Now(),
		}
		s.quotas[userID] = quota
	}

	quota.UsedQuota += usedBytes
	quota.LastCheckTime = time.Now()

	return nil
}

// IsQuotaExceeded 检查是否超出配额
func (s *InMemoryQuotaStorage) IsQuotaExceeded(userID string) (bool, *TrafficQuota, error) {
	s.mu.RLock()
	defer s.mu.RUnlock()

	quota, exists := s.quotas[userID]
	if !exists {
		// 不存在则不超出
		return false, nil, nil
	}

	// 检查是否需要重置配额
	if time.Now().After(quota.ResetTime) {
		// 需要重置，但这里只读锁，返回未超出
		return false, quota, nil
	}

	exceeded := quota.UsedQuota >= quota.TotalQuota
	return exceeded, quota, nil
}

// TrafficQuotaInterceptor 流量配额拦截器
type TrafficQuotaInterceptor struct {
	storage TrafficQuotaStorage
	enabled bool // 是否启用（用于快速开关）
}

// NewTrafficQuotaInterceptor 创建流量配额拦截器
func NewTrafficQuotaInterceptor(storage TrafficQuotaStorage) *TrafficQuotaInterceptor {
	if storage == nil {
		storage = NewInMemoryQuotaStorage()
	}

	return &TrafficQuotaInterceptor{
		storage: storage,
		enabled: true, // 默认启用
	}
}

// Name 拦截器名称
func (i *TrafficQuotaInterceptor) Name() string {
	return "TrafficQuotaInterceptor"
}

// Priority 优先级（10 = 高优先级，先检查流量配额）
func (i *TrafficQuotaInterceptor) Priority() int {
	return 10
}

// Enable 启用拦截器
func (i *TrafficQuotaInterceptor) Enable() {
	i.enabled = true
	log.Printf("💰 [计费] 流量配额拦截器已启用")
}

// Disable 禁用拦截器
func (i *TrafficQuotaInterceptor) Disable() {
	i.enabled = false
	log.Printf("💰 [计费] 流量配额拦截器已禁用")
}

// Intercept 拦截逻辑
func (i *TrafficQuotaInterceptor) Intercept(ctx *InterceptContext) (*InterceptResult, error) {
	// 如果禁用，直接放行
	if !i.enabled {
		return nil, nil
	}

	// 检查是否超出配额
	exceeded, quota, err := i.storage.IsQuotaExceeded(ctx.UserID)
	if err != nil {
		return nil, fmt.Errorf("检查流量配额失败: %v", err)
	}

	if exceeded {
		log.Printf("🚫 [计费] 流量配额超出: UserID=%s, Used=%d, Total=%d",
			ctx.UserID, quota.UsedQuota, quota.TotalQuota)

		// 返回不可用结果
		return &InterceptResult{
			Available:   false,
			Reason:      fmt.Sprintf("流量配额已用尽 (已使用: %.2f GB / %.2f GB)", float64(quota.UsedQuota)/(1024*1024*1024), float64(quota.TotalQuota)/(1024*1024*1024)),
			PaymentType: quota.PaymentType,
			PaymentURL:  quota.PaymentURL,
			OrderID:     quota.OrderID,
			Extra: map[string]interface{}{
				"used_bytes":  quota.UsedQuota,
				"total_bytes": quota.TotalQuota,
				"reset_time":  quota.ResetTime.Format(time.RFC3339),
			},
		}, nil
	}

	// 🚀 未超出配额，记录本次请求流量（后续处理）
	// 注意：这里只记录请求流量，响应流量需要在请求完成后记录
	if ctx.RequestSize > 0 {
		if err := i.storage.UpdateUsage(ctx.UserID, ctx.RequestSize); err != nil {
			log.Printf("⚠️  [计费] 更新流量使用失败: %v", err)
		}
	}

	// 放行
	return nil, nil
}

// RecordResponseTraffic 记录响应流量（在请求处理完成后调用）
func (i *TrafficQuotaInterceptor) RecordResponseTraffic(userID string, responseSize int64) error {
	if !i.enabled || responseSize <= 0 {
		return nil
	}

	return i.storage.UpdateUsage(userID, responseSize)
}

// GetStorage 获取存储实例（用于外部设置配额）
func (i *TrafficQuotaInterceptor) GetStorage() TrafficQuotaStorage {
	return i.storage
}
